gtkwindow: Revoke implicit grabs when activating an explicit one
authorCarlos Garnacho <carlosg@gnome.org>
Sat, 1 Apr 2017 20:38:02 +0000 (22:38 +0200)
committerCarlos Garnacho <carlosg@gnome.org>
Thu, 25 May 2017 14:25:59 +0000 (16:25 +0200)
Only if they fall outside the grab widget, in that case the widget holding
the implicit grab won't be receiving events anymore, so we can just undo
it.

gtk/gtkwindow.c
gtk/gtkwindowgroup.c
gtk/gtkwindowprivate.h

index d6efac75ee9fce7d8660f910cf39b6ea47fdb3e1..f0e8f07125d1d4ba5a730caa2749d200880adff8 100644 (file)
@@ -11470,6 +11470,34 @@ gtk_window_update_pointer_focus_on_state_change (GtkWindow *window,
     }
 }
 
+void
+gtk_window_maybe_revoke_implicit_grab (GtkWindow *window,
+                                       GdkDevice *device,
+                                       GtkWidget *grab_widget)
+{
+  GList *l = window->priv->foci, *cur;
+
+  while (l)
+    {
+      GtkPointerFocus *focus = l->data;
+
+      cur = l;
+      focus = cur->data;
+      l = cur->next;
+
+      if (focus->toplevel != window)
+        continue;
+
+      if (device && focus->device == device &&
+          focus->target != grab_widget &&
+          !gtk_widget_is_ancestor (focus->target, grab_widget))
+        gtk_window_set_pointer_focus_grab (window,
+                                           focus->device,
+                                           focus->sequence,
+                                           NULL);
+    }
+}
+
 void
 gtk_window_set_pointer_focus_grab (GtkWindow        *window,
                                    GdkDevice        *device,
index bb1265065f153cd68152776102df47ec312929cd..38befc5a4cfb151515f12246d0ad6c66cb8a4466 100644 (file)
@@ -253,6 +253,25 @@ gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
   return NULL;
 }
 
+static void
+revoke_implicit_grabs (GtkWindowGroup *window_group,
+                       GdkDevice      *device,
+                       GtkWidget      *grab_widget)
+{
+  GList *windows, *l;
+
+  windows = gtk_window_group_list_windows (window_group);
+
+  for (l = windows; l; l = l->next)
+    {
+      gtk_window_maybe_revoke_implicit_grab (l->data,
+                                             device,
+                                             grab_widget);
+    }
+
+  g_list_free (windows);
+}
+
 void
 _gtk_window_group_add_grab (GtkWindowGroup *window_group,
                             GtkWidget      *widget)
@@ -261,6 +280,8 @@ _gtk_window_group_add_grab (GtkWindowGroup *window_group,
 
   priv = window_group->priv;
   priv->grabs = g_slist_prepend (priv->grabs, widget);
+
+  revoke_implicit_grabs (window_group, NULL, widget);
 }
 
 void
@@ -290,6 +311,8 @@ _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
   info->block_others = block_others;
 
   priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
+
+  revoke_implicit_grabs (window_group, device, widget);
 }
 
 void
index 7d8d18965d4e107f2830da8e914f2a3a9561f615..857121985ec6d79d14b3cab766208a26a6dadc2f 100644 (file)
@@ -161,6 +161,10 @@ void             gtk_window_set_pointer_focus_grab (GtkWindow        *window,
 void             gtk_window_update_pointer_focus_on_state_change (GtkWindow *window,
                                                                   GtkWidget *widget);
 
+void             gtk_window_maybe_revoke_implicit_grab (GtkWindow *window,
+                                                        GdkDevice *device,
+                                                        GtkWidget *grab_widget);
+
 G_END_DECLS
 
 #endif /* __GTK_WINDOW_PRIVATE_H__ */